<?php

namespace App\Kuafu\Wechat\Service\Event;

use App\Kuafu\Activity\Enum\ActivityEnum;
use App\Kuafu\Activity\Exceptions\ActivityException;
use App\Kuafu\Activity\Model\ActivityImageMappingModel;
use App\Kuafu\Activity\Service\ActivityService;
use App\Kuafu\Base\Model\BaseModel;
use App\Kuafu\Base\Service\BaseService;
use App\Kuafu\Config\Service\ConfigService;
use App\Kuafu\Customer\Enum\PlatformCodeEnum;
use App\Kuafu\Customer\Model\CustomerActionLogModel;
use App\Kuafu\Customer\Model\CustomerPlatformModel;
use App\Kuafu\Customer\Service\CustomerActionLogService;
use App\Kuafu\Shop\Enum\ShopCodeEnum;
use App\Kuafu\Shop\Service\ShopAppletService;
use App\Kuafu\Shop\Service\ShopService;
use App\Kuafu\Wechat\Enum\CodeEnum;
use App\Kuafu\Wechat\Service\WechatCallbackService;
use App\Kuafu\Wechat\Service\WechatConfigService;
use App\Support\AppletEncrypt;
use GuzzleHttp\Client as GuzzleClient;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Log;

class WechatEvent
{

    private array  $postData;
    private array  $qrDecryptData;
    private string $event;
    private string $openId;
    private array  $activityInfo;

    public function __construct(array $postObj)
    {
        $this->postData = $postObj;
        $this->event    = $postObj['Event'];
        $this->openId   = $postObj['FromUserName'];

        Log::channel('wechat')->info('receive wechat event data', $postObj);
    }

    public function handle()
    {
        $method = 'handle' . ucfirst($this->event);
        Log::channel('wechat')->info('event method', [$this->event, $method]);
        if (method_exists($this, $method)) {
            return $this->$method();
        }
    }

    /**
     * 订阅关注事件
     *
     * @throws GuzzleException
     */
    private function handleSubscribe()
    {
        // 处理用户登录操作
        $this->userSubscribe();

        // 存在参数处理
        Log::channel('wechat')->debug('1', $this->postData);

        if (!empty($this->postData['EventKey'])) {
            // 携带参数扫码关注
            $this->doSubEventKey();
        } else {
            // 普通人关注
            // 公众号 被动 回复消息
            $content = CodeEnum::APPLET_EVENT_AUTO;
            echo $content == '' ? 'success' : self::replyPassiveMessageFormat($content);
        }


//        // 被动回复消息
//        $content = CodeEnum::APPLET_EVENT_AUTO;
//        echo $content == '' ? 'success' : self::replyPassiveMessageFormat($content);

    }

    /**
     * 取关事件
     *
     * @return void
     */
    private function handleUnsubscribe()
    {
        $this->userUnsubscribe();
    }

    private function handleScan()
    {
        // 存在参数处理
        if (!empty($this->postData['EventKey'])) {
            // 携带参数扫码关注
            $this->doSubEventKey();
        } else {
            // 普通人关注
            // 被动回复消息
            $content = CodeEnum::APPLET_EVENT_AUTO;
            echo $content == '' ? 'success' : self::replyPassiveMessageFormat($content);
        }
    }

    private function handleLocation()
    {
        return '上报地理位置';
    }

    private function handleClick()
    {
        return '点击菜单';
    }

    private function handleView()
    {
        return '点击菜单跳转链接';
    }

    /**
     * 用户关注事件
     *
     * @return void
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    private function userSubscribe()
    {
        // 获取到open_Id
        // 通过 openId 获取 UnionId
        $wxUserInfo = WechatCallbackService::getUserinfo($this->openId);
        $userInfo   = CustomerPlatformModel::query()->firstOrCreate([
            'openid'     => $this->openId,
            'unionid'    => $wxUserInfo['unionid'],
            'platformId' => PlatformCodeEnum::PLATFORM_APPLET_OFFICIAL,
        ]);

        $appletUserinfo = CustomerPlatformModel::query()->where([
            'unionid'    => $wxUserInfo['unionid'],
            'platformId' => PlatformCodeEnum::PLATFORM_APPLET_WECHAT_APPLET,
        ])->first();

        // 首次关注
//        if (!empty($appletUserinfo) && $appletUserinfo->userId != 0) {
        $userInfo->userId = $appletUserinfo->userId ?? 0;
        $userInfo->save();

        // 公众号关注处理用户日志
        (new CustomerActionLogService())->dealOfficeUserData($this->postData, $userInfo);
//        }
    }


    private function userUnsubscribe()
    {
        // 获取到open_Id, 并软删除
        $user = CustomerPlatformModel::query()
                                     ->where([
                                         'openId'     => $this->openId,
                                         'platformId' => PlatformCodeEnum::PLATFORM_APPLET_OFFICIAL,
                                     ])
                                     ->first();

        if (!empty($user)) {
            $user->isDeleted = BaseModel::DELETE_YES;
            $user->save();
        }

        // 用户取关
        (new CustomerActionLogService())->asynSaveData([
            'userId'   => $user->userId ?? 0,
            'unionId'  => $user->unionid ?? '',
            'type'     => CustomerActionLogModel::ACTION_TYPE_OFFICIAL_UNFOLLOW,
            'userInfo' => [
                'openId' => $this->openId
            ]
        ]);

    }

    /**
     * 格式化 被动回复消息
     *
     * @return void
     */
    private function replyPassiveMessageFormat($content): string
    {
        $toUsername   = $this->postData['ToUserName'];
        $fromUsername = $this->postData['FromUserName'];
        $time         = time();
        $textTpl      = "<xml>
                        <ToUserName><![CDATA[%s]]></ToUserName>
                        <FromUserName><![CDATA[%s]]></FromUserName>
                        <CreateTime>%s</CreateTime>
                        <MsgType><![CDATA[text]]></MsgType>
                        <Content><![CDATA[%s]]></Content>
                    </xml>";
        return sprintf($textTpl, $fromUsername, $toUsername, $time, $content);
    }

    /**
     * @throws GuzzleException
     */
    private function doSubEventKey()
    {
        if (!empty($this->postData['EventKey']) && strpos($this->postData['EventKey'],
                CodeEnum::APPLET_EVENT_KEY) !== false) {
            list(, $jsonStr) = explode(':', $this->postData['EventKey']);

            $decryptShort = AppletEncrypt::getInstance()->decryptShort($jsonStr, CodeEnum::APPLET_EVENT_KEY);
            $qrCodeData   = json_decode($decryptShort, true);

            Log::channel('wechat')->info('doSubEventKey EventKey 解密：', $qrCodeData);

            $this->qrDecryptData = $qrCodeData;

            switch ($qrCodeData['type']) {
                case CodeEnum::APPLET_EVENT_TYPE_SHOP:// 点餐
                    Log::channel('wechat')->info('扫码获取小程序点单', $this->qrDecryptData);
                    // 推送小程序点单
                    $this->doEventTypeAppletOrder();
                    break;
                case CodeEnum::APPLET_EVENT_TYPE_ACTIVITY:// 活动
                    // 判断已存在的活动涉及门店

                    $shopInfo      = ShopService::getShopInfo($this->getShopIdByDecryptData());
                    $limitShopList = WechatConfigService::getLimitShopList();
                    $keyLists      = array_keys($limitShopList);

                    // 现有的活动,2023 年 10 月 1 日之后 这块逻辑可以删除
                    if (in_array($shopInfo['shopCode'], $keyLists)) {
                        Log::channel('wechat')->info('扫码获取活动详情-老：' . $this->getShopIdByDecryptData());
                        // 活动二维码
                        $this->doEventTypeActivity();
                    } else {
                        Log::channel('wechat')->info('扫码获取活动详情-新：' . $this->getShopIdByDecryptData());
                        $this->doEventTypeActivityV2();
                    }

                    break;
                default :
                    Log::channel('wechat')->info('无事件消息');
                    break;
            }
        }
    }

    /**
     * 扫码推送小程序推送小程序点餐
     *
     * @throws GuzzleException
     */
    private function doEventTypeAppletOrder(): void
    {
        $this->doEventTypeAppletOrderSendApplet();
    }


    /**
     * 推送小程序卡片
     *
     * @return void
     */
    private function doEventTypeAppletOrderSendApplet()
    {
        $token      = WechatCallbackService::getAccessToken();
        $token      = $token['access_token'];
        $shopId     = $this->getShopIdByDecryptData();
        $appletInfo = ShopAppletService::getAppletInfo($shopId);
        //查询店铺信息
        if ($shopId > 0) {
            $shopInfo = ShopService::getShopInfo($shopId);
            $shopCode = str_pad($shopInfo['shopCode'], ShopCodeEnum::CODE_TEXT[ShopCodeEnum::LEADING_ZERO], "0",
                STR_PAD_LEFT);
            $title    = '您选择了' . $shopCode . $shopInfo['name'];
            Log::channel('wechat')->info('店铺信息：' . $title);
            $url   = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=" . $token;
            $title = urlencode($title);
            $title = urldecode($title);
            Log::channel('wechat')->info('店铺信息加密解密：' . $title);
            //查询最新的mediaId
            $appletConfig = ConfigService::getConfigInfoByValue([
                'key'  => CodeEnum::APPLET_CARD_KEY,
                'type' => CodeEnum::APPLET_CARD_TYPE
            ], ['value']);
            $data         = [
                'touser'          => $this->postData['FromUserName'],
                'msgtype'         => 'miniprogrampage',
                'miniprogrampage' => [
                    'title'          => $title,//小程序卡片的标题
                    'appid'          => $appletInfo['appId'],
                    'pagepath'       => config('wechat.indexPagePath') . '?shopId=' . $shopId,
//                    'pagepath'       => 'pages/activity/store-opening?id=1525&shopId=14450',
                    'thumb_media_id' => $appletConfig['value'],
                ]
            ];
            $client       = new GuzzleClient();
            $body         = json_encode($data, JSON_UNESCAPED_UNICODE);
            Log::channel('wechat')->info("发送小卡片入参：" . $body);
            $response = $client->request("POST", $url, ['body' => $body, 'timeout' => 10]);
            $response = $response->getBody()->getContents();
            Log::channel('wechat')->info("发送小卡片结果：" . $response);
//            json_decode($response, true);
        }
    }

    /**
     * 扫码活动
     *
     * @param array $qrCodeData
     * @return void
     * @throws GuzzleException
     */
    private function doEventTypeActivity()
    {
        // 发送欢迎语
        self::sendUserTextMessage(self::getLatestText());

        // 开业活动
        self::doEventTypeActivityMessage();
    }

    public function getActivityInfo(): array
    {
        return $this->activityInfo;
    }

    /**
     * @throws ActivityException
     */
    public function setActivityInfo(int $activityId): void
    {
        $this->activityInfo = ActivityService::getActivityDetailByInfo($activityId);
    }

    /**
     * 扫码活动
     *
     * @param array $qrCodeData
     * @return void
     * @throws GuzzleException
     */
    private function doEventTypeActivityV2()
    {
        // 判断是否存在相应的活动
        $activityId = self::getActivityIdByType();

        if (!$activityId) {

            self::sendUserTextMessage(self::getActivityExpiredPushText());

            return;
        }

        self::setActivityInfo($activityId);

        // 发送欢迎语
        self::sendUserTextMessage(self::getActivityPushText());

        // 开业活动
        self::doEventTypeActivityMessageV2();
    }

    private function sendUserTextMessage(string $content)
    {
        Log::channel('wechat')->info('微信单发文字消息', [
            'content' => $content
        ]);
        $token = WechatCallbackService::getAccessToken();
        $token = $token['access_token'];

        $url    = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=" . $token;
        $data   = [
            'touser'  => $this->postData['FromUserName'],
            'msgtype' => 'text',
            'text'    => [
                'content' => $content
            ]
        ];
        $client = new GuzzleClient();
        $body   = json_encode($data, JSON_UNESCAPED_UNICODE);
        Log::channel('wechat')->info("微信单发文字消息 入参：" . $body);
        $response = $client->request("POST", $url, ['body' => $body, 'timeout' => 10]);
        $response = $response->getBody()->getContents();
        Log::channel('wechat')->info("微信单发文字消息 结果：" . $response);
    }


    /**
     * 开业活动临时活动代码
     *
     * @return void
     */
    private function doEventTypeActivityMessage()
    {
        Log::channel('wechat')->info('活动消息: 推送活动图片');
        $token  = WechatCallbackService::getAccessToken();
        $token  = $token['access_token'];
        $shopId = $this->getShopIdByDecryptData();
        //查询店铺信息

        $url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=" . $token;

        // 获取开业活动的 ID
        $activityId = ActivityService::getActivityIdByShopInfo(ActivityEnum::TYPE_START_BUSINESS_ACTIVITY, $shopId);

        // 如果活动为空
        if (!$activityId) {
            return [];
        }

        $shopInfo = ShopService::getShopInfo($shopId);

        $limitShopList = WechatConfigService::getLimitShopList();

        $mediaId = $limitShopList[$shopInfo['shopCode']]['mediaId'] ?? '';

//        Log::channel('wechat')->debug('testYkk', [
//            '$limitShopList' => $limitShopList,
//            'shopCode'       => $shopInfo['shopCode'],
//            '$mediaId'       => $mediaId
//        ]);

        $data   = [
            'touser'  => $this->postData['FromUserName'],
            'msgtype' => 'image',
            "image"   =>
                [
                    "media_id" => $mediaId,
                ]
        ];
        $client = new GuzzleClient();
        $body   = json_encode($data, JSON_UNESCAPED_UNICODE);
        Log::channel('wechat')->info("发送小卡片入参：" . $body);
        $response = $client->request("POST", $url, ['body' => $body, 'timeout' => 10]);
        $response = $response->getBody()->getContents();
        Log::channel('wechat')->info("发送小卡片结果：" . $response);
        return json_decode($response, true);
    }

    private function getActivityIdByType()
    {
        $shopId = $this->getShopIdByDecryptData();

        $activityId = ActivityService::getActivityIdByShopInfo(ActivityEnum::TYPE_START_BUSINESS_ACTIVITY, $shopId);

        return $activityId;
    }

    private function doEventTypeActivityMessageV2()
    {
        Log::channel('wechat')->info('活动消息: doEventTypeActivityMessageQa');

        $shopId = $this->getShopIdByDecryptData();
        //查询店铺信息
        $shopInfo = ShopService::getShopInfo($shopId);

        // 手动置顶
        $sendType = 3; // 1 发送图片 2 发送消息 3 发送小程序


        switch ($sendType) {
            case 1:
                // 获取活动的图片
                $limitShopList = WechatConfigService::getLimitShopList();
                $mediaId       = $limitShopList[$shopInfo['shopCode']]['mediaId'] ?? '';
                $data          = [
                    'touser'  => $this->postData['FromUserName'],
                    'msgtype' => 'image',
                    "image"   =>
                        [
                            "media_id" => $mediaId,
                        ]
                ];
                break;
            case 3 :

                // 获取小程序卡片的图片


                $miniCardThumb = collect($this->activityInfo['imageList'])
                    ->where('type', ActivityImageMappingModel::TYPE_MINI_IMAGE_INNER)->first();


                if (empty($miniCardThumb)) {
                    $thumbMediaId = 'Lt4oTEK8yM6Y_qmRAs-3LfzREoEZvD82Lp9aIWnTCz8vFC3B81807NswiWYNOyIE';
                } else {
                    $thumbMediaId = $miniCardThumb->imageUrl;
                    Log::channel('wechat')->debug('yyy', [$miniCardThumb]);
//                    $thumbMediaId = 'Lt4oTEK8yM6Y_qmRAs-3LXnoSfyvXWXvQCESwhOSNXuyYXsZpDevTx2n1Yr21E7u';
                }
                $appletInfo = ShopAppletService::getAppletInfo($shopId);
                $data       = [
                    'touser'          => $this->postData['FromUserName'],
                    'msgtype'         => 'miniprogrampage',
                    'miniprogrampage' => [
                        'title'          => '戳我👇加福利官, 领专享福利', //小程序卡片的标题
                        'appid'          => $appletInfo['appId'],
                        'pagepath'       => 'pages/activity/friend-shop?shopId=' . $shopId,
                        'thumb_media_id' => $thumbMediaId,
                    ]
                ];
                Log::channel('wechat')->debug("开业活动消息发送-开始：", $data);
                break;
        }

        $client = new GuzzleClient();
        $body   = json_encode($data, JSON_UNESCAPED_UNICODE);
        Log::channel('wechat')->info("开业活动消息发送-开始：" . $body);
        $token    = WechatCallbackService::getAccessToken();
        $token    = $token['access_token'];
        $url      = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=" . $token;
        $response = $client->request("POST", $url, ['body' => $body, 'timeout' => 10]);
        $response = $response->getBody()->getContents();
        Log::channel('wechat')->info("开业活动消息发送-结果：" . $response);
        return json_decode($response, true);
    }


    private function getShopIdByDecryptData()
    {
        return (int)($this->qrDecryptData['shopId'] ?? 0);
    }

    private function getActivityPushText()
    {
        return $this->activityInfo['basis']['pushText'] ?? '欢迎关注!';
    }

    /**
     * 过期活动的推送文案
     *
     * @return mixed|string
     */
    private function getActivityExpiredPushText()
    {
        return '🥰小可爱，您来迟啦，当前活动已结束
✊下次记得早点来哦～ 

💖不要走开，关注我享粉丝专属活动...';
    }


    private function getLatestText()
    {
        $shopInfo = ShopService::getShopInfo(self::getShopIdByDecryptData());
        switch ($shopInfo['shopCode']) {
            case 1288:
            case 1777:
                return "😘hi，你好哇！
            
👏🏻欢迎成为夸父炸串的新朋友！

💖初次见面，送您一份见面礼～
👇🏻长按扫码添加【福利官】，免费吃「夸父大里脊」

🤙夸父炸串好吃，更值得加盟～
🔍宝，记得探索底部菜单，发现精彩";
                break;
            default:
                return "😘hi，你好哇！

👏🏻欢迎成为夸父炸串的新朋友！

💖初次见面，送您一份见面礼～
👇🏻长按扫码添加【福利官】，免费吃「巴掌大鸡排」

🤙夸父炸串好吃，更值得加盟～
🔍宝，记得探索底部菜单，发现精彩";
                break;
        }
    }


}
